include([], function(){
	declare('CanvasWrapper');
	
	CanvasWrapper = function(canvas){
		this.canvas = canvas;
		this.strokeStyle = 'black';
		this.fillStyle   = 'black';
		this.shadowOffsetX = 0.0;
		this.shadowOffsetY = 0.0;
		this.shadowBlur   = 0.0;
		this.lineWidth    = 1;
		this.shadowColor  = 'transparent black';
		this.font         = '10px sans-serif';
		this.textAlign    = 'start';
		this.textBaseline = 'alphabetic';
		this.drawn = [];
	};
	CanvasWrapper.prototype = {
		_initFont : function(){
			this.canvas.font = this.font;
			this.canvas.textAlign = this.textAlign;
			this.canvas.textBaseline = this.textBaseline;
		},
		_initPath : function(){
			this.canvas.strokeStyle = this.strokeStyle;
			this.canvas.fillStyle = this.fillStyle;
			this.canvas.shadowOffsetX = this.shadowOffsetX;
			this.canvas.shadowOffsetY = this.shadowOffsetY;
			this.canvas.shadowBlur = this.shadowBlur;
			this.canvas.shadowColor = this.shadowColor;
			this.canvas.lineWidth = this.lineWidth;
		},
		_record : function(x,y,width,height){
			var padding = 2 + this.lineWidth*2;
			this.drawn.push({x:x-padding,y:y-padding,width:width+(padding*2),height:height+(padding*2)});
		},	
		clear : function(){
			var tmp = this.drawn;
			var scope = this;
			this.drawn = [];

			iterate(tmp, function(rect){
				scope.clearRect(rect.x, rect.y, rect.width, rect.height);
			});
		},		
		save : function(){
			this.canvas.save();
		},
		restore : function(){
			this.canvas.restore();
			
			this.strokeStyle = this.canvas.strokeStyle;
			this.fillStyle = this.canvas.fillStyle;
			this.shadowOffsetX = this.canvas.shadowOffsetX;
			this.shadowOffsetY = this.canvas.shadowOffsetY;
			this.shadowBlur = this.canvas.shadowBlur;
			this.shadowColor = this.canvas.shadowColor;
			this.lineWidth = this.canvas.lineWidth;
			
			this.font = this.canvas.font;
			this.textAlign = this.canvas.textAlign;
			this.textBaseline = this.canvas.textBaseline;
		},
		scale : function(x,y){
			this.canvas.scale(x,y);
		},
		rotate : function(angle){
			this.canvas.rotate(angle);
		},
		translate : function(x, y){
			this.canvas.translate(x,y);
		},
		transform : function(m11, m12, m21, m22, dx, dy){
			this.canvas.transform(m11,m12,m21,m22,dx,dy);
		},
		setTransform : function(m11, m12, m21, m22, dx, dy){
			this.canvas.setTransform(m11,m12,m21,m22,dx,dy);
		},
		drawImage : function(){
			var image, dx, dy, dw, dh;
			var sx,sy,sw,sh;
			
			image = arguments[0]
			if( arguments.length == 9 ){
				sx = arguments[1]
				sy = arguments[2]
				sw = arguments[3]
				sh = arguments[4]
				dx = arguments[5]
				dy = arguments[6]
				dw = arguments[7]
				dh = arguments[8]
				this.canvas.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh);
				this._record(dx, dy, dw, dh);
			}else if(arguments.length == 5){
				dx = arguments[1]
				dy = arguments[2]
				dw = arguments[3]
				dh = arguments[4]
				this.canvas.drawImage(image,dx,dy,dw,dh);
				this._record(dx, dy, dw, dh);
			}else{
				dx = arguments[1]
				dy = arguments[2]
				this.canvas.drawImage(image,dx,dy);
				this._record(dx, dy, image.width, image.height);
			}
		},
		createLinearGradient : function(x0, y0, x1, y1){
			return this.canvas.createLinearGradient(x0, y0, x1, y1);
		},
		createRadialGradient : function(x0, y0, r0, x1, y1, r1){
			return this.canvas.createRadialGradient(x0, y0, r0, x1, y1, r1);
		},
		createPattern : function(image, repetition){
			return this.canvas.createPattern(image,repetition);
		},
		beginPath : function(){
			this.canvas.beginPath();
		},
		closePath : function(){
			this.canvas.closePath();
		},
		fill : function(){
			this._initPath();
			this.canvas.fill();
		},
		stroke : function(){
			this._initPath();
			this.canvas.stroke();
		},
		clip : function(){
			this._initPath();
			this.canvas.clip();
		},
		moveTo : function(x,y){
			this.canvas.moveTo(x,y);
		},
		lineTo : function(x,y){
			this._initPath();
			this.canvas.lineTo(x,y);
		},
		quadraticCurveTo : function(cpx, cpy, x, y){
			this._initPath();
			this.canvas.quadraticCurveTo(cpx, cpy, x, y);
		},
		bezierCurveTo : function(cp1x, cp1y, cp2x, cp2y, x ,y){
			this._initPath();
			this.canvas.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x ,y);
		},
		arcTo : function(x1, y1, x2, y2, radius){
			this._initPath();
			this.canvas.arcTo(x1,y1,x2,y2,radius);
			this._record(x1, y1, x2-x1+radius, y2-y1+radius);
		},
		arc : function(x, y, radius, startAngle, endAngle, anticlockwise){
			this._initPath();
			this.canvas.arc(x,y,radius,startAngle, endAngle, anticlockwise);
			this._record(x-radius, y-radius, radius*2, radius*2);
		},
		rect : function(x,y,w,h){
			this._initPath();
			this.canvas.rect(x,y,w,h);
			this._record(x, y, w, h);
		},
		isPointInPath : function(x, y){
			return this.canvas.isPointInPath(x,y)
		},
		fillText : function(text, x,y, maxWidth){
			this._initFont();
			this._initPath();
			this.canvas.fillText(text,x,y,maxWidth)
			this._record(x-10, y-20, this.measureText(text).width+10, 62);
		},
		strokeText : function(text, x, y, maxWidth){
			this._initFont();
			this._initPath();
			this.canvas.strokeText(text,x,y,maxWidth)
			this._record(x-10, y-20, this.measureText(text).width+10, 62);
		},
		measureText : function(text){
			return this.canvas.measureText(text);
		},
		clearRect : function(x,y,w,h){
			this.canvas.clearRect(x,y,w,h);
		},
		fillRect : function(x,y,w,h){
			this.canvas.fillRect(x,y,w,h);
			this._record(x, y, w, h);
		},
		strokeRect : function(x,y,w,h){
			this.canvas.strokeRect(x,y,w,h);
			this._record(x, y, w, h);
		},
		createImageData : function(sw, sh){
			return this.canvas.createImageData(sw,sh);
		},
		getImageData : function(sx, sy, sw, sh){
			return this.canvas.getImageData(sx,sy,sw,sh);
		},
		putImageData : function(imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight){
			this.canvas.putImageData(imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
		}
	};	
})